﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using AForge.Video.DirectShow;
using System.Drawing.Imaging;
using System.Threading;
using System.IO;
using AForge.Controls;
using circle_progressbar;
using System.Web.Script.Serialization;
using System.Collections;
using System.Data.Odbc;
namespace VCMW
{
    public partial class FrmFaceSingin : Form
    {
        public FrmFaceSingin()
        {
            InitializeComponent();
            this.DoubleBuffered = true;//设置本窗体
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
        }

        #region 公共变量
        bool debug = false;
        Debug debugFrm = new Debug();
        //获取线上会议地址
        //string meeting_url = "http://ggbxcwx.ydm01.cn/api/meeting_system/meetingListForFace";//测试环境地址
        string meeting_url = "http://xcwx.ydm01.cn/api/meeting_system/meetingListForFace";//正式环境地址
        //线上人脸签到API
        //string facesigin_url = "http://ggbxcwx.ydm01.cn/api/faceplus/face_signin";//测试环境地址
        string facesigin_url = "http://xcwx.ydm01.cn/api/faceplus/face_signin";//正式环境地址
        //string facesigin_url = "http://localhost:9996/api/faceplus/face_signin";
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x0014) // 禁掉清除背景消息
                return;
            base.WndProc(ref m);
        }
        messageboxHelper box = new messageboxHelper();
        private FilterInfoCollection videoDevices;//调取摄像头
        Logs log = new Logs();
        List<String> list = new List<String>();
        string meetingID = "";//会议ID
        string temppath = "";
        //获取项目的根目录
        String path = Directory.GetCurrentDirectory();
        #endregion

        #region 加载事件
        //加载
        private void FrmFaceSingin_Load(object sender, EventArgs e)
        {
            try
            {
                this.pictureBox2.Visible = false;
                this.videoSourcePlayer1.Visible = false;
                string tempdata = createHttp(meeting_url, "serialNumber=A01");
                JObject JOBJ = (JObject)JsonConvert.DeserializeObject(tempdata);
                JToken data = JOBJ.GetValue("data");
                Array arr = data.ToArray();
                for (int i = 0; i < arr.Length; i++)
                {
                    string[] tempa = arr.GetValue(i).ToString().Split(':');
                    string[] tempb = tempa[1].Split(',');//会议id
                    string[] tempc = tempa[2].Split(',');//会议名称
                    string tempname = tempc[0].Substring(2, tempc[0].Length - 3);
                    list.Add(tempb[0] + "-会议名称：" + tempname);
                }
                showRadioButton(arr.Length, list);

                //this.pictureBox1.BackColor = Color.FromArgb(9, 9, 24);
                this.panel3.Visible = false;
                this.MaximizeBox = false;
                this.MinimizeBox = false;
                //设置窗口边框
                this.ControlBox = false;
                this.FormBorderStyle = FormBorderStyle.None;
                //设置panel居中显示
                panel3.Location = setControlLocationToCenter(this.panel1.Width, panel1.Location.Y, this.panel3.Width);
                this.pictureBox1.Visible = true;
                this.panel3.BackColor = Color.FromArgb(153, 220, 220, 220);
                this.label1.Text = "";

                //this.pictureBox1.ImageLocation=temppath + "\\Resources\\男@3x.png";
                string[] path_arr = path.Split('\\');
                for (int i = 0; i < path_arr.Length; i++)
                {
                    if (path_arr[i].Trim().ToString() == "VCMW")
                    {
                        temppath += path_arr[i];
                        break;
                    }
                    else
                    {
                        temppath += path_arr[i] + "\\";
                    }
                }
                //this.BackColor = Color.FromArgb(9, 9, 24);
                // 枚举所有视频输入设备
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                if (videoDevices.Count == 0)
                {
                    log.WriteLog("未检测到摄像头。");
                    this.panel3.Visible = true;
                    this.labtitle.Text = "未检测到摄像头";
                    labtitle.Location = setControlLocationToCenter(this.panel3.Width, labtitle.Location.Y, this.labtitle.Width);
                    label1.Text = "加载失败";
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\x.png";
                    return;
                }

                //设置跨线程操作
                Control.CheckForIllegalCrossThreadCalls = false;
                if (debug)
                {
                    debugFrm.Show();
                }
            }
            catch (ApplicationException)
            {
                return;
            }
        }
        #endregion

        #region 自动关闭的messagebox
        /// <summary>
        /// 测试1，使用方式
        /// </summary>
        public void test1()
        {
            dlgCircle_progressBar bar = new dlgCircle_progressBar();
            //需要异步处理的工作//参数可指定超时时间,消息提示
            bar.Progression((obj, args) =>
            {
                for (var currNum = 0; currNum <= 99; currNum++)
                {
                    bar.ProgressUpdate(currNum, 99);//处理过程中改变百分比
                    Thread.Sleep(20);//耗时操作
                }
            }, 20, "");
            bar.ShowDialog(this);//开启等待窗口
            //异步工作完成后或超时后，交由'本'线程继续处理
            string overtimeMsg = bar.Message;
            if (!string.IsNullOrEmpty(overtimeMsg))//消息非空为超时
            {
                MessageBox.Show(bar.Message);
            }
        }
        #endregion

        #region 视频处理
        /*
        //bool currentlyAnimating = false;
        //Bitmap animatedImage = new Bitmap(@"E:\code\faceRecognition\VCMW\Resources\sm2-2.gif");
        ////This method begins the animation.
        //public void AnimateImage()
        //{
        //    if (!currentlyAnimating)
        //    {

        //        //Begin the animation only once.
        //        ImageAnimator.Animate(animatedImage, new EventHandler(this.OnFrameChanged));
        //        currentlyAnimating = true;
        //    }
        //}
        //private void OnFrameChanged(object o, EventArgs e)
        //{
        //    //Force a call to the Paint event handler.
        //    this.Invalidate();
        //}
        //protected override void OnPaint(PaintEventArgs e)
        //{
        //    Graphics gp = videoSourcePlayer1.CreateGraphics();
        //    //Begin the animation.
        //    AnimateImage();

        //    //Get the next frame ready for rendering.
        //    ImageAnimator.UpdateFrames();

        //    //Draw the next frame in the animation.
        //    gp.DrawImage(this.animatedImage, 200, 100);
        //}
        */
        /// <summary>
        /// 打开摄像头
        /// </summary>
        public void openCan()
        {
            //连接摄像头。
            VideoCaptureDevice videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
            videoSource.VideoResolution = videoSource.VideoCapabilities[0];
            // 枚举所有摄像头支持的像素，设置拍照为1920*1080
            foreach (VideoCapabilities capab in videoSource.VideoCapabilities)
            {
                if (capab.FrameSize.Width == 1920 && capab.FrameSize.Height == 1080)
                {
                    videoSource.VideoResolution = capab;
                    break;
                }
                if (capab.FrameSize.Width == 1280 && capab.FrameSize.Height == 720)
                {
                    videoSource.VideoResolution = capab;
                    break;
                }
            }
            videoSourcePlayer1.NewFrame += new VideoSourcePlayer.NewFrameHandler(videoSourcePlayer1_NewFrame);
            videoSourcePlayer1.VideoSource = videoSource;
            //开启摄像头
            videoSourcePlayer1.Start();
        }

        int width = 0;
        int height = 0;
        int radius_x = 0;
        int radius_y = 0;
        int radius_8y = 0;
        private void videoSourcePlayer1_NewFrame(object sender, ref Bitmap image)
        {
            Image img = System.Drawing.Image.FromFile(temppath + "\\Resources\\facesm.png");        //粘贴的图片
            Graphics gph = Graphics.FromImage(image);
            //这个区域包括任务栏，就是屏幕显示的物理范围
            Rectangle ScreenArea = System.Windows.Forms.Screen.GetBounds(this);
            width = ScreenArea.Width / 3;
            height = ScreenArea.Height / 2;
            radius_x = ScreenArea.Width / 4;
            radius_y = ScreenArea.Height / 4;
            radius_8y = ScreenArea.Height / 8;
            //Pen myPen = new Pen(Color.Blue, 4);
            //int left_top_x = x;
            //int left_top_y = y;
            //int left_bottom_x = left_top_x;
            //int left_bottom_y = left_top_y + height;
            //int right_top_x = left_top_x + width;
            //int right_top_y = left_top_y;
            //int right_bottom_x = left_bottom_x + width;
            //int right_bottom_y = left_bottom_y;
            ////gph.DrawEllipse(myPen, x, y, width, height);//画椭圆的方法，x坐标、y坐标、宽、高，如果是100，则半径为50
            gph.DrawImage(img, radius_x, radius_y - radius_8y, width, height);
            GC.Collect();
        }
        #endregion

        #region 定时器及事件
        //创建定时器
        System.Timers.Timer timer = new System.Timers.Timer();
        System.Timers.Timer timer2 = new System.Timers.Timer();
        //定时器
        private void inteverTime()
        {
            debugFrm.outPutDebug(string.Format("开始执行timer1111\r\n "));
            timer.Enabled = true;
            timer.Interval =1300;//执行间隔时间,单位为毫秒
            timer.Start();
            timer.Elapsed += new System.Timers.ElapsedEventHandler(faceRecognition);
        }
        private void inteverTime2()
        {
            debugFrm.outPutDebug(string.Format("开始执行timer2222\r\n "));
            timer2.Enabled = true;
            timer2.Interval = 1300;//执行间隔时间,单位为毫秒
            timer2.Start();
            timer2.Elapsed += new System.Timers.ElapsedEventHandler(faceRecognition2);
        }
        //定时执行事件
        private void faceRecognition(object source, System.Timers.ElapsedEventArgs e)
        {
            debugFrm.outPutDebug(string.Format("停止执行timer1111\r\n "));
            timer.Stop();
            this.pictureBox2.Visible = false;
            Image tempImage = pictureBox2.Image;
            pictureBox2.Image = null;
            if (tempImage != null)
            {
                tempImage.Dispose();
            }
            this.panel3.Visible = false;
            this.label1.Text = "人脸识别中";
            labtitle.Text = "";
            label1.Location = setControlLocationToCenter(this.panel2.Width, label1.Location.Y, this.label1.Width);
            try
            {
                //获取视频流
                Bitmap bitmap = videoSourcePlayer1.GetCurrentVideoFrame();
                if (videoSourcePlayer1 == null || bitmap == null)
                {
                    this.panel3.Visible = true;
                    this.labtitle.Text = "图像加载失败";
                    labtitle.Location = setControlLocationToCenter(this.panel3.Width, labtitle.Location.Y, this.labtitle.Width);
                    log.WriteLog("图像加载失败");
                    inteverTime2();
                    return;
                }
                //this.Refresh();

                Dictionary<string, object> verifyPostParameters = new Dictionary<string, object>();
                verifyPostParameters.Add("api_key", "K8C6bsfZQdylnN-FVuMFr6xZ29HxQrsk");//正式
                verifyPostParameters.Add("api_secret", "P-RRNnW-VMFZrZLeezFq5lBflMC6IZEU");
                //verifyPostParameters.Add("api_key", "YCtNBLKcbjWR7NUFJCgxMH9JekkBRqsa");//试用
                //verifyPostParameters.Add("api_secret", "L4YiS_YbR93k7eifMWQQNIkEIr-15_Fn");
                verifyPostParameters.Add("outer_id", "1");
                verifyPostParameters.Add("face_rectangle", "" + (radius_y - radius_8y) + "," + radius_x + "," + width + "," + height + "");
                MemoryStream ms = new MemoryStream();//内存流
                bitmap.Save(ms, ImageFormat.Jpeg);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();
                verifyPostParameters.Add("image_base64", Convert.ToBase64String(arr));
                this.progressBar1.Value = 20;
                //人脸搜索结果
                string xx = createHttps("https://api-cn.faceplusplus.com/facepp/v3/search", verifyPostParameters);
                JObject ja = (JObject)JsonConvert.DeserializeObject(xx);
                this.progressBar1.Value = 40;
                
                if (ja.ContainsKey("error_message"))
                {
                    log.WriteLog(ja.ToString());
                    this.label1.Text = "识别失败，请重试";
                    label1.Location = setControlLocationToCenter(this.panel2.Width, label1.Location.Y, this.label1.Width);
                    //this.pictureBox2.ImageLocation = temppath + "\\Resources\\failed1.jpg";
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\failed1.jpg";
                    this.pictureBox2.Visible = true;
                    inteverTime2();
                    return;
                }
                else if (!ja.ContainsKey("results"))
                {
                    this.panel3.Visible = true;
                    this.labtitle.Text = "请把人脸移到屏幕中";
                    labtitle.Location = setControlLocationToCenter(this.panel3.Width, labtitle.Location.Y, this.labtitle.Width);
                    log.WriteLog(ja.ToString());
                    this.label1.Text = "识别失败，请重试";
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\failed1.jpg";
                    this.pictureBox2.Visible = true;
                    inteverTime2();
                    //this.pictureBox2.ImageLocation = temppath + "\\Resources\\failed1.jpg";
                    return;
                }

                debugFrm.outPutDebug(string.Format("人脸搜索得到的face_token:{0:f}\r\n ", ja["results"][0]["face_token"].ToString()));
                //人脸签到参数
                string postdata = "";
                if (Convert.ToInt32(ja["results"][0]["confidence"]) > Convert.ToInt32(ja["thresholds"]["1e-5"]))
                {
                    string[] tempa = meetingID.Split('-');
                    postdata = "data=" + ja["results"][0]["face_token"].ToString() + "-" + tempa[0].Trim();
                }
                else
                {
                    log.WriteLog("图片匹配相似度低，请重新扫描！" + ja.ToString());
                    this.label1.Text = "您可能未提交照片喔";
                    label1.Location = setControlLocationToCenter(this.panel2.Width, label1.Location.Y, this.label1.Width);
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\failed1.jpg";
                    this.pictureBox2.Visible = true;
                    inteverTime2();
                    return;
                    //box.Show("您可能未提交照片喔！", "提示", 1000);
                }
                //调取人脸签到API
                xx = createHttp(facesigin_url, postdata);
                ja = (JObject)JsonConvert.DeserializeObject(xx);

                this.progressBar1.Value = 80;
                if (ja["status"].ToString() == "500")
                {
                    this.progressBar1.Value = 100;
                    log.WriteLog(xx);
                    //this.pictureBox1.Visible = false;
                    //this.pictureBox2.Visible = true;
                    this.label1.Text = "识别失败，请重试";
                    inteverTime2();
                    return;
                    //box.Show("识别失败，请重新尝试！", "提示", 1000);
                }
                else if (Convert.ToInt32(ja["data"]) >= 1)
                {
                    this.progressBar1.Value = 100;
                    log.WriteLog("签到成功！" + postdata);
                    this.label1.Text = "识别成功，欢迎您的到来";
                    label1.Location = setControlLocationToCenter(this.panel2.Width, label1.Location.Y, this.label1.Width);
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\success1.png";
                    this.pictureBox2.Visible = true;
                    inteverTime2();
                    return;
                    //box.Show("识别成功，欢迎您的到来！", "提示", 1000);
                }
                else if (Convert.ToInt32(ja["data"]) == -1)
                {
                    this.progressBar1.Value = 100;
                    log.WriteLog("已签到！" + postdata);
                    this.label1.Text = "您已经签到过啦";
                    label1.Location = setControlLocationToCenter(this.panel2.Width, label1.Location.Y, this.label1.Width);
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\success1.png";
                    this.pictureBox2.Visible = true;
                    inteverTime2();
                    return;
                    //box.Show("您已经签到过啦！", "提示", 1000);
                }
                else
                {
                    this.progressBar1.Value = 100;
                    log.WriteLog("数据库中不存在你的图片！" + postdata);
                    this.label1.Text = "您可能未提交照片喔";
                    label1.Location = setControlLocationToCenter(this.panel2.Width, label1.Location.Y, this.label1.Width);
                    this.pictureBox2.ImageLocation = temppath + "\\Resources\\failed1.jpg";
                    this.pictureBox2.Visible = true;
                    inteverTime2();
                    return;
                    //box.Show("您可能未提交照片喔！", "提示", 1000);
                }
            }
            catch (Exception err)
            {
                log.WriteLog(err.ToString());
                return;
            }
        }
        private void faceRecognition2(object source, System.Timers.ElapsedEventArgs e)
        {
            timer.Start();
        }

        #endregion

        #region http及HTTPS请求函数
        //发送 http 请求函数
        private string createHttp(string url, string postData)
        {
            //定义request并设置request的路径
            WebRequest request = WebRequest.Create(url);

            //定义请求的方式
            request.Method = "POST";

            //设置参数的编码格式，解决中文乱码
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            //设置request的MIME类型及内容长度
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = byteArray.Length;

            //打开request字符流
            Stream dataStream = request.GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();

            //定义response为前面的request响应
            WebResponse response = request.GetResponse();

            //获取相应的状态代码
            Console.WriteLine(((HttpWebResponse)response).StatusDescription);

            //定义response字符流
            dataStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream);
            string responseFromServer = reader.ReadToEnd();//读取所有
            Console.WriteLine(responseFromServer);

            //关闭资源
            reader.Close();
            dataStream.Close();
            response.Close();
            return responseFromServer;
        }

        //发送人脸识别 https 请求函数
        private string createHttps(string url, Dictionary<string, object> verifyPostParameters)
        {
            HttpWebResponse verifyResponse = HttpHelper4MultipartForm.MultipartFormDataPost(url, "", verifyPostParameters);
            Stream str = verifyResponse.GetResponseStream();
            StreamReader str1 = new StreamReader(str);
            string xx = str1.ReadToEnd();
            return xx;
        }
        #endregion

        #region 窗体关闭相关事件
        private void FrmFaceSingin_KeyPress(object sender, KeyPressEventArgs e)
        {
            //ESC退出
            if (e.KeyChar == (char)27)
            {
                Environment.Exit(0);
                return;
            }
        }

        private void FrmFaceSingin_FormClosing(object sender, FormClosingEventArgs e)
        {
            Application.ExitThread();
            Environment.Exit(0);
        }

        #endregion

        #region 获取所有会议
        private string getMeeting(string url)
        {

            string data = createHttp(url, "serialNumber=A01");
            //JObject ja = (JObject)JsonConvert.DeserializeObject(data);
            return data;
        }
        #endregion

        #region  动态设置控件
        /// <summary>
        /// 动态设置控件位置
        /// </summary>
        /// <param name="widthParent">父控件宽度</param>
        /// <param name="controlY">子控件Y轴坐标</param>
        /// <param name="widthChild">子控件宽度</param>
        /// <returns></returns>
        private System.Drawing.Point setControlLocationToCenter(int widthParent, int controlY, int widthChild)
        {
            int x = (int)(0.5 * (widthParent - widthChild));
            int y = controlY;
            System.Drawing.Point po = new System.Drawing.Point(x, y);
            return po;
        }

        //提交单选按钮结果
        private void btn_radio_Click(object sender, EventArgs e)
        {
            Control.ControlCollection sonControls = panel1.Controls;
            foreach (Control c in sonControls)
            {
                if (c is RadioButton)
                {
                    if (((RadioButton)c).Checked == true)
                    {
                        meetingID = ((RadioButton)c).Text;
                    }
                    c.Visible = false;
                }
            }
            this.btn_radio.Visible = false;
            this.videoSourcePlayer1.Visible = true;
            //打开摄像头
            openCan();
            //调用定时器
            inteverTime();
        }

        //动态添加控件
        public void showRadioButton(int listSize, List<String> list)
        {
            //控件上边缘与容器上边缘的距离  
            int top = 100;
            //记录循环，控件左上角相对于容器左上角的坐标  
            int i = 0;
            int n = 0;
            RadioButton[] radioButton = new RadioButton[listSize];
            for (n = 0; n < listSize; n++)
            {
                if (n % 15 == 0 && n != 0)
                {
                    i++;
                    if (i % 5 == 0)
                    {
                        top = 6 * n;
                        i = 0;
                    }
                    else
                    {
                        top = 6;
                    }
                }
                radioButton[n] = new RadioButton();
                radioButton[n].AutoSize = true;
                radioButton[n].Top = top;
                //控件左上角相对于容器左上角的坐标，以及每个控件之间的距离  
                radioButton[n].Location = new Point(i * 150 + 50, top);
                // MessageBox.Show(name[n].ToString());  
                radioButton[n].Text = list[n].ToString();
                radioButton[n].Visible = true;
                radioButton[n].Name = "radioButton" + n;
                radioButton[n].ForeColor = Color.White;
                this.panel1.Controls.Add(radioButton[n]);
                top = top + 21;
            }
        }
        #endregion
    }
}
